/*
 * Created on Jul 8, 2004
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License");  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * http//www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is MAPONTO.
 *
 * The Initial Developer of the Original Code is University of Toronto. Portions
 * created by University of Toronto are Copyright (C) 2004.  All Rights Reserved.
 *
 * MAPONTO was developed by Knowledge Management Lab
 * (http//www.cs.toronto.edu/km) at the University of Toronto Department of 
 * Computer Science. Current information about MAPONTO can be obtained at 
 * http//resi.ai.toronto.edu:8080
 *
 */

/*
 * Contributor(s): Yuan An yuana@cs.toronto.edu
*/
package main.model;

import java.io.Serializable;
import java.util.ArrayList;

import main.graph.ValuedGraph;
import y.base.Edge;
import y.base.Node;
import edu.stanford.smi.protegex.owl.model.OWLProperty;

/**Representation of the association edge between classes.
 * @author Yuan An
 */
public class Relationship implements Comparable, OntoEle, Serializable{
	public static final int SPECIALIZATION = 0;
	public static final int INSTANCE = 1;
	public static final int ASSOCIATION = 2;
	public static final int REIFIEDROLE=3;
	public static final int COMBINEDREIFIED=4;
	public static final int ATTRIBUTE = 5;
	public static final int SPACEHOLDER = 6;

	private OntoEle source;
	private OntoEle target;
	
	private OWLProperty refProperty;
	private OWLProperty refInverseProperty;
	private Edge refEdge;
	private String name;
	private Cardinality sourceBound;
	private Cardinality targetBound;
	private boolean isInherited;
	private double weight;
	private int type;
	private Relationship inverse;
	private boolean isInverseFunctional;
	private boolean isParticipant;
	private boolean isCollapsed;
	
	//a set of slots containing all slots of merged edges
	private ArrayList<OWLProperty> mergedProperties;
	
	/*the reified node which this edge should pass through if
	 * replaced by original two edges.
	 */
	private Entity reified;
	/*indicates that this edge is the combined two reified edges.*/
	private boolean isCombinedReified;
	
	public Relationship(OntoEle source, OntoEle target,
		OWLProperty refProperty,
		Edge refEdge,
		String name,
		int type,
		Cardinality sourceCardi,
		Cardinality targetCardi) {
		this.source = source;
		this.target = target;
		this.refProperty = refProperty;
		this.refInverseProperty = null;
		this.refEdge = refEdge;
		this.name = name;
		sourceBound = sourceCardi;
		targetBound = targetCardi;
		isInherited = false;
		weight = 0;
		this.type = type;
		inverse = null;
		isInverseFunctional = false;
		isParticipant=false;
		reified=null;
		isCombinedReified=false;
		isCollapsed=false;
		mergedProperties = new ArrayList<OWLProperty>();
		if(refProperty!=null)
			mergedProperties.add(refProperty);
	}
	
	public OntoEle getSource(){
		return source;
	}
	
	public void setSource(OntoEle source){
		this.source = source;
	}
	
	public OntoEle getTarget(){
		return target;
	}
	
	public void setTarget(OntoEle target){
		this.target = target;
	}

	public void addMergedProperty(OWLProperty property){
		mergedProperties.add(property);
	}
	
	public ArrayList<OWLProperty> getMergedProperties(){
		return mergedProperties;
	}
	
	public OWLProperty getRefProperty() {
		return refProperty;
	}

	public OWLProperty getRefInverseProperty(){
		return refInverseProperty;
	}
	
	public String getRefInversePropertyName(){
		if(refInverseProperty != null)
			return refInverseProperty.getBrowserText();
		
		return null;
	}
	
	public void setRefInverseProperty(OWLProperty p){
		refInverseProperty = p;
	}
	
	public Edge getRefEdge() {
		return refEdge;
	}

	public Cardinality getSourceCardinality() {
		return sourceBound;
	}

	public Cardinality getTargetCardinality() {
		return targetBound;
	}
	
	public void setName(String name){
		this.name=name;
	}

	public String getName() {
		return name;
	}

	public boolean isInherited() {
		return isInherited;
	}

	public boolean isInverseFunctional() {
		return isInverseFunctional;
	}

	public double getWeight() {
		return weight;
	}

	public int getType() {
		return type;
	}

	public Relationship getInverse() {
		return inverse;
	}
	
	public Entity getReifiedClassNode(){
		return reified;
	}
	
	public boolean isCombinedReified(){
		return isCombinedReified;
	}

	public boolean isCollapsed(){
		return isCollapsed;
	}
	
	public void setCollapsed(){
		isCollapsed=true;
	}
	
	public void setType(int type){
		this.type=type;
	}


	public void setInverse(Relationship edge) {
		inverse = edge;
	}

	public void setSourceCardinality(Cardinality sc) {
		sourceBound = sc;
	}

	public void setTargetCardinality(Cardinality tc) {
		targetBound = tc;
	}

	public void setInheritied() {
		isInherited = true;
	}

	public void setWeight(double w) {
		weight = w;
	}
	
	public boolean isParticipant(){
		return isParticipant;
	}
	
	public void setParticipant(){
		isParticipant=true;
	}
	
	public void setReifiedClassNode(Entity node){
		reified=node;
	}
	
	public void setIsCombinedReified(){
		isCombinedReified=true;
	}

	public int compareTo(Object o1){
		int ans=1;
		
		Relationship other=(Relationship)o1;
		
		if(weight < other.weight)
			ans = -1;
		else if (weight == other.weight)
			ans = 0;
			
		return ans;	
	}
	

	public void setInverseFunctional() {
		isInverseFunctional = true;
	}

	public String display() {
		String ans="";
		
		//if(source != null)
			ans += "[" + source.getName() + "]";
		//else
			//ans += "[]";
		
		ans += "-<" + name + ">-";
		//if(target != null)
			ans += "[" + target.getName() + "]";
		//else 
			//ans += "[]";
		
		return ans;
	}
}
